home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / me39src1.arc / WORD.C < prev   
C/C++ Source or Header  |  1987-07-15  |  14KB  |  560 lines

  1. /*
  2.  * The routines in this file implement commands that work word or a
  3.  * paragraph at a time.  There are all sorts of word mode commands.  If I
  4.  * do any sentence mode commands, they are likely to be put in this file. 
  5.  */
  6.  
  7. #include    <stdio.h>
  8. #include    "estruct.h"
  9. #include    "edef.h"
  10.  
  11. /* Word wrap on n-spaces. Back-over whatever precedes the point on the current
  12.  * line and stop on the first word-break or the beginning of the line. If we
  13.  * reach the beginning of the line, jump back to the end of the word and start
  14.  * a new line.    Otherwise, break the line at the word-break, eat it, and jump
  15.  * back to the end of the word.
  16.  * Returns TRUE on success, FALSE on errors.
  17.  */
  18. wrapword(f, n)
  19.  
  20. int f;        /* default flag */
  21. int n;        /* numeric argument */
  22.  
  23. {
  24.     register int cnt;    /* size of word wrapped to next line */
  25.     register int c;        /* charector temporary */
  26.  
  27.     /* backup from the <NL> 1 char */
  28.     if (!backchar(0, 1))
  29.         return(FALSE);
  30.  
  31.     /* back up until we aren't in a word,
  32.        make sure there is a break in the line */
  33.     cnt = 0;
  34.     while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
  35.                 && (c != '\t')) {
  36.         cnt++;
  37.         if (!backchar(0, 1))
  38.             return(FALSE);
  39.         /* if we make it to the beginning, start a new line */
  40.         if (curwp->w_doto == 0) {
  41.             gotoeol(FALSE, 0);
  42.             return(lnewline());
  43.         }
  44.     }
  45.  
  46.     /* delete the forward white space */
  47.     if (!forwdel(0, 1))
  48.         return(FALSE);
  49.  
  50.     /* put in a end of line */
  51.     if (!lnewline())
  52.         return(FALSE);
  53.  
  54.     /* and past the first word */
  55.     while (cnt-- > 0) {
  56.         if (forwchar(FALSE, 1) == FALSE)
  57.             return(FALSE);
  58.     }
  59.     return(TRUE);
  60. }
  61.  
  62. /*
  63.  * Move the cursor backward by "n" words. All of the details of motion are
  64.  * performed by the "backchar" and "forwchar" routines. Error if you try to
  65.  * move beyond the buffers.
  66.  */
  67. backword(f, n)
  68. {
  69.     if (n < 0)
  70.         return (forwword(f, -n));
  71.     if (backchar(FALSE, 1) == FALSE)
  72.         return (FALSE);
  73.     while (n--) {
  74.         while (inword() == FALSE) {
  75.             if (backchar(FALSE, 1) == FALSE)
  76.                 return (FALSE);
  77.         }
  78.         while (inword() != FALSE) {
  79.             if (backchar(FALSE, 1) == FALSE)
  80.                 return (FALSE);
  81.         }
  82.     }
  83.     return (forwchar(FALSE, 1));
  84. }
  85.  
  86. /*
  87.  * Move the cursor forward by the specified number of words. All of the motion
  88.  * is done by "forwchar". Error if you try and move beyond the buffer's end.
  89.  */
  90. forwword(f, n)
  91. {
  92.     if (n < 0)
  93.         return (backword(f, -n));
  94.     while (n--) {
  95.         while (inword() == TRUE) {
  96.             if (forwchar(FALSE, 1) == FALSE)
  97.                 return (FALSE);
  98.         }
  99.  
  100.         while (inword() == FALSE) {
  101.             if (forwchar(FALSE, 1) == FALSE)
  102.                 return (FALSE);
  103.         }
  104.     }
  105.     return(TRUE);
  106. }
  107.  
  108. /*
  109.  * Move the cursor forward by the specified number of words. As you move,
  110.  * convert any characters to upper case. Error if you try and move beyond the
  111.  * end of the buffer. Bound to "M-U".
  112.  */
  113. upperword(f, n)
  114. {
  115.     register int    c;
  116.  
  117.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  118.         return(rdonly());    /* we are in read only mode    */
  119.     if (n < 0)
  120.         return (FALSE);
  121.     while (n--) {
  122.         while (inword() == FALSE) {
  123.             if (forwchar(FALSE, 1) == FALSE)
  124.                 return (FALSE);
  125.         }
  126.         while (inword() != FALSE) {
  127.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  128.             if (c>='a' && c<='z') {
  129.                 c -= 'a'-'A';
  130.                 lputc(curwp->w_dotp, curwp->w_doto, c);
  131.                 lchange(WFHARD);
  132.             }
  133.             if (forwchar(FALSE, 1) == FALSE)
  134.                 return (FALSE);
  135.         }
  136.     }
  137.     return (TRUE);
  138. }
  139.  
  140. /*
  141.  * Move the cursor forward by the specified number of words. As you move
  142.  * convert characters to lower case. Error if you try and move over the end of
  143.  * the buffer. Bound to "M-L".
  144.  */
  145. lowerword(f, n)
  146. {
  147.     register int    c;
  148.  
  149.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  150.         return(rdonly());    /* we are in read only mode    */
  151.     if (n < 0)
  152.         return (FALSE);
  153.     while (n--) {
  154.         while (inword() == FALSE) {
  155.             if (forwchar(FALSE, 1) == FALSE)
  156.                 return (FALSE);
  157.         }
  158.         while (inword() != FALSE) {
  159.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  160.             if (c>='A' && c<='Z') {
  161.                 c += 'a'-'A';
  162.                 lputc(curwp->w_dotp, curwp->w_doto, c);
  163.                 lchange(WFHARD);
  164.             }
  165.             if (forwchar(FALSE, 1) == FALSE)
  166.                 return (FALSE);
  167.         }
  168.     }
  169.     return (TRUE);
  170. }
  171.  
  172. /*
  173.  * Move the cursor forward by the specified number of words. As you move
  174.  * convert the first character of the word to upper case, and subsequent
  175.  * characters to lower case. Error if you try and move past the end of the
  176.  * buffer. Bound to "M-C".
  177.  */
  178. capword(f, n)
  179. {
  180.     register int    c;
  181.  
  182.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  183.         return(rdonly());    /* we are in read only mode    */
  184.     if (n < 0)
  185.         return (FALSE);
  186.     while (n--) {
  187.         while (inword() == FALSE) {
  188.             if (forwchar(FALSE, 1) == FALSE)
  189.                 return (FALSE);
  190.         }
  191.         if (inword() != FALSE) {
  192.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  193.             if (c>='a' && c<='z') {
  194.                 c -= 'a'-'A';
  195.                 lputc(curwp->w_dotp, curwp->w_doto, c);
  196.                 lchange(WFHARD);
  197.             }
  198.             if (forwchar(FALSE, 1) == FALSE)
  199.                 return (FALSE);
  200.             while (inword() != FALSE) {
  201.                 c = lgetc(curwp->w_dotp, curwp->w_doto);
  202.                 if (c>='A' && c<='Z') {
  203.                     c += 'a'-'A';
  204.                     lputc(curwp->w_dotp, curwp->w_doto, c);
  205.                     lchange(WFHARD);
  206.                 }
  207.                 if (forwchar(FALSE, 1) == FALSE)
  208.                     return (FALSE);
  209.             }
  210.         }
  211.     }
  212.     return (TRUE);
  213. }
  214.  
  215. /*
  216.  * Kill forward by "n" words. Remember the location of dot. Move forward by
  217.  * the right number of words. Put dot back where it was and issue the kill
  218.  * command for the right number of characters. With a zero argument, just
  219.  * kill one word and no whitespace. Bound to "M-D".
  220.  */
  221. delfword(f, n)
  222. {
  223.     register LINE    *dotp;    /* original cursor line */
  224.     register int    doto;    /*    and row */
  225.     register int c;        /* temp char */
  226.     long size;        /* # of chars to delete */
  227.  
  228.     /* don't allow this command if we are in read only mode */
  229.     if (curbp->b_mode&MDVIEW)
  230.         return(rdonly());
  231.  
  232.     /* ignore the command if there is a negative argument */
  233.     if (n < 0)
  234.         return (FALSE);
  235.  
  236.     /* Clear the kill buffer if last command wasn't a kill */
  237.     if ((lastflag&CFKILL) == 0)
  238.         kdelete();
  239.     thisflag |= CFKILL;    /* this command is a kill */
  240.  
  241.     /* save the current cursor position */
  242.     dotp = curwp->w_dotp;
  243.     doto = curwp->w_doto;
  244.  
  245.     /* figure out how many characters to give the axe */
  246.     size = 0;
  247.  
  248.     /* get us into a word.... */
  249.     while (inword() == FALSE) {
  250.         if (forwchar(FALSE, 1) == FALSE)
  251.             return(FALSE);
  252.         ++size;
  253.     }
  254.  
  255.     if (n == 0) {
  256.         /* skip one word, no whitespace! */
  257.         while (inword() == TRUE) {
  258.             if (forwchar(FALSE, 1) == FALSE)
  259.                 return(FALSE);
  260.             ++size;
  261.         }
  262.     } else {
  263.         /* skip n words.... */
  264.         while (n--) {
  265.     
  266.             /* if we are at EOL; skip to the beginning of the next */
  267.             while (curwp->w_doto == llength(curwp->w_dotp)) {
  268.                 if (forwchar(FALSE, 1) == FALSE)
  269.                     return(FALSE);
  270.                 ++size;
  271.             }
  272.     
  273.             /* move forward till we are at the end of the word */
  274.             while (inword() == TRUE) {
  275.                 if (forwchar(FALSE, 1) == FALSE)
  276.                     return(FALSE);
  277.                 ++size;
  278.             }
  279.     
  280.             /* if there are more words, skip the interword stuff */
  281.             if (n != 0)
  282.                 while (inword() == FALSE) {
  283.                     if (forwchar(FALSE, 1) == FALSE)
  284.                         return(FALSE);
  285.                     ++size;
  286.                 }
  287.         }
  288.     
  289.         /* skip whitespace and newlines */
  290.         while ((curwp->w_doto == llength(curwp->w_dotp)) ||
  291.             ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ') ||
  292.             (c == '\t')) {
  293.                 if (forwchar(FALSE, 1) == FALSE)
  294.                     break;
  295.                 ++size;
  296.         }
  297.     }
  298.  
  299.     /* restore the original position and delete the words */
  300.     curwp->w_dotp = dotp;
  301.     curwp->w_doto = doto;
  302.     return (ldelete(size, TRUE));
  303. }
  304.  
  305. /*
  306.  * Kill backwards by "n" words. Move backwards by the desired number of words,
  307.  * counting the characters. When dot is finally moved to its resting place,
  308.  * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
  309.  */
  310. delbword(f, n)
  311. {
  312.     long size;
  313.  
  314.     /* don't allow this command if we are in read only mode */
  315.     if (curbp->b_mode&MDVIEW)
  316.         return(rdonly());
  317.  
  318.     /* ignore the command if there is a nonpositive argument */
  319.     if (n <= 0)
  320.         return (FALSE);
  321.  
  322.     /* Clear the kill buffer if last command wasn't a kill */
  323.     if ((lastflag&CFKILL) == 0)
  324.         kdelete();
  325.     thisflag |= CFKILL;    /* this command is a kill */
  326.  
  327.     if (backchar(FALSE, 1) == FALSE)
  328.         return (FALSE);
  329.     size = 0;
  330.     while (n--) {
  331.         while (inword() == FALSE) {
  332.             if (backchar(FALSE, 1) == FALSE)
  333.                 return (FALSE);
  334.             ++size;
  335.         }
  336.         while (inword() != FALSE) {
  337.             ++size;
  338.             if (backchar(FALSE, 1) == FALSE)
  339.                 goto bckdel;
  340.         }
  341.     }
  342.     if (forwchar(FALSE, 1) == FALSE)
  343.         return (FALSE);
  344. bckdel:    return (ldelete(size, TRUE));
  345. }
  346.  
  347. /*
  348.  * Return TRUE if the character at dot is a character that is considered to be
  349.  * part of a word. The word character list is hard coded. Should be setable.
  350.  */
  351. inword()
  352. {
  353.     register int    c;
  354.  
  355.     if (curwp->w_doto == llength(curwp->w_dotp))
  356.         return (FALSE);
  357.     c = lgetc(curwp->w_dotp, curwp->w_doto);
  358.     if (c>='a' && c<='z')
  359.         return (TRUE);
  360.     if (c>='A' && c<='Z')
  361.         return (TRUE);
  362.     if (c>='0' && c<='9')
  363.         return (TRUE);
  364.     return (FALSE);
  365. }
  366.  
  367. #if    WORDPRO
  368. fillpara(f, n)    /* Fill the current paragraph according to the current
  369.            fill column                        */
  370.  
  371. int f, n;    /* deFault flag and Numeric argument */
  372.  
  373. {
  374.     register int c;            /* current char durring scan    */
  375.     register int wordlen;        /* length of current word    */
  376.     register int clength;        /* position on line during fill    */
  377.     register int i;            /* index during word copy    */
  378.     register int newlength;        /* tentative new line length    */
  379.     register int eopflag;        /* Are we at the End-Of-Paragraph? */
  380.     register int firstflag;        /* first word? (needs no space)    */
  381.     register LINE *eopline;        /* pointer to line just past EOP */
  382.     register int dotflag;        /* was the last char a period?    */
  383.     char wbuf[NSTRING];        /* buffer for current word    */
  384.  
  385.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  386.         return(rdonly());    /* we are in read only mode    */
  387.     if (fillcol == 0) {    /* no fill column set */
  388.         mlwrite("No fill column set");
  389.         return(FALSE);
  390.     }
  391.  
  392.     /* record the pointer to the line just past the EOP */
  393.     gotoeop(FALSE, 1);
  394.     eopline = lforw(curwp->w_dotp);
  395.  
  396.     /* and back top the beginning of the paragraph */
  397.     gotobop(FALSE, 1);
  398.  
  399.     /* initialize various info */
  400.     clength = curwp->w_doto;
  401.     if (clength && curwp->w_dotp->l_text[0] == TAB)
  402.         clength = 8;
  403.     wordlen = 0;
  404.     dotflag = FALSE;
  405.  
  406.     /* scan through lines, filling words */
  407.     firstflag = TRUE;
  408.     eopflag = FALSE;
  409.     while (!eopflag) {
  410.         /* get the next character in the paragraph */
  411.         if (curwp->w_doto == llength(curwp->w_dotp)) {
  412.             c = ' ';
  413.             if (lforw(curwp->w_dotp) == eopline)
  414.                 eopflag = TRUE;
  415.         } else
  416.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  417.  
  418.         /* and then delete it */
  419.         ldelete(1L, FALSE);
  420.  
  421.         /* if not a separator, just add it in */
  422.         if (c != ' ' && c != '\t') {
  423.             dotflag = (c == '.');        /* was it a dot */
  424.             if (wordlen < NSTRING - 1)
  425.                 wbuf[wordlen++] = c;
  426.         } else if (wordlen) {
  427.             /* at a word break with a word waiting */
  428.             /* calculate tantitive new length with word added */
  429.             newlength = clength + 1 + wordlen;
  430.             if (newlength <= fillcol) {
  431.                 /* add word to current line */
  432.                 if (!firstflag) {
  433.                     linsert(1, ' '); /* the space */
  434.                     ++clength;
  435.                 }
  436.                 firstflag = FALSE;
  437.             } else {
  438.                 /* start a new line */
  439.                 lnewline();
  440.                 clength = 0;
  441.             }
  442.  
  443.             /* and add the word in in either case */
  444.             for (i=0; i<wordlen; i++) {
  445.                 linsert(1, wbuf[i]);
  446.                 ++clength;
  447.             }
  448.             if (dotflag) {
  449.                 linsert(1, ' ');
  450.                 ++clength;
  451.             }
  452.             wordlen = 0;
  453.         }
  454.     }
  455.     /* and add a last newline for the end of our new paragraph */
  456.     lnewline();
  457.     return(TRUE);
  458. }
  459.  
  460. killpara(f, n)    /* delete n paragraphs starting with the current one */
  461.  
  462. int f;    /* default flag */
  463. int n;    /* # of paras to delete */
  464.  
  465. {
  466.     register int status;    /* returned status of functions */
  467.  
  468.     while (n--) {        /* for each paragraph to delete */
  469.  
  470.         /* mark out the end and beginning of the para to delete */
  471.         gotoeop(FALSE, 1);
  472.  
  473.         /* set the mark here */
  474.         curwp->w_markp = curwp->w_dotp;
  475.         curwp->w_marko = curwp->w_doto;
  476.  
  477.         /* go to the beginning of the paragraph */
  478.         gotobop(FALSE, 1);
  479.         curwp->w_doto = 0;    /* force us to the beginning of line */
  480.     
  481.         /* and delete it */
  482.         if ((status = killregion(FALSE, 1)) != TRUE)
  483.             return(status);
  484.  
  485.         /* and clean up the 2 extra lines */
  486.         ldelete(2L, TRUE);
  487.     }
  488.     return(TRUE);
  489. }
  490.  
  491.  
  492. /*    wordcount:    count the # of words in the marked region,
  493.             along with average word sizes, # of chars, etc,
  494.             and report on them.            */
  495.  
  496. wordcount(f, n)
  497.  
  498. int f, n;    /* ignored numeric arguments */
  499.  
  500. {
  501.     register LINE *lp;    /* current line to scan */
  502.     register int offset;    /* current char to scan */
  503.     long size;        /* size of region left to count */
  504.     register int ch;    /* current character to scan */
  505.     register int wordflag;    /* are we in a word now? */
  506.     register int lastword;    /* were we just in a word? */
  507.     long nwords;        /* total # of words */
  508.     long nchars;        /* total number of chars */
  509.     int nlines;        /* total number of lines in region */
  510.     int avgch;        /* average number of chars/word */
  511.     int status;        /* status return code */
  512.     REGION region;        /* region to look at */
  513.  
  514.     /* make sure we have a region to count */
  515.     if ((status = getregion(®ion)) != TRUE)
  516.         return(status);
  517.     lp = region.r_linep;
  518.     offset = region.r_offset;
  519.     size = region.r_size;
  520.  
  521.     /* count up things */
  522.     lastword = FALSE;
  523.     nchars = 0L;
  524.     nwords = 0L;
  525.     nlines = 0;
  526.     while (size--) {
  527.  
  528.         /* get the current character */
  529.         if (offset == llength(lp)) {    /* end of line */
  530.             ch = '\n';
  531.             lp = lforw(lp);
  532.             offset = 0;
  533.             ++nlines;
  534.         } else {
  535.             ch = lgetc(lp, offset);
  536.             ++offset;
  537.         }
  538.  
  539.         /* and tabulate it */
  540.         wordflag = ((ch >= 'a' && ch <= 'z') ||
  541.                 (ch >= 'A' && ch <= 'Z') ||
  542.                 (ch >= '0' && ch <= '9'));
  543.         if (wordflag == TRUE && lastword == FALSE)
  544.             ++nwords;
  545.         lastword = wordflag;
  546.         ++nchars;
  547.     }
  548.  
  549.     /* and report on the info */
  550.     if (nwords > 0L)
  551.         avgch = (int)((100L * nchars) / nwords);
  552.     else
  553.         avgch = 0;
  554.  
  555.     mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
  556.         nwords, nchars, nlines + 1, avgch);
  557.     return(TRUE);
  558. }
  559. #endif
  560.